/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * uiChartView.java
 *
 * Created on Jun 22, 2012, 10:08:58 AM
 */
package taskspydelux;

import com.skstudio.reportview.ReportViewController;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.logging.Logger;

/**
 *
 * @author wenwei
 */
public class uiChartView extends javax.swing.JPanel implements MouseListener, KeyListener {

    public void keyTyped(KeyEvent e) {
        if (mHilitedColumn == -1) {
            return;
        }

        if (e.getKeyChar() == '1') {
            mHilitedColumn++;

            int cols = mController.getReportColumns();
            if (mHilitedColumn > cols - 1) {
                mHilitedColumn = cols - 1;
            }

            notifyHilightChanged();
        }
        if (e.getKeyChar() == '2') {
            mHilitedColumn--;

            if (mHilitedColumn < 0) {
                mHilitedColumn = 0;
            }

            notifyHilightChanged();
        }
    }

    public void keyPressed(KeyEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void keyReleased(KeyEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public interface uiChartViewListener {

        public void onSelectionChanged(int curCol);
    };
    uiChartViewListener mEventListener = null;

    public void setEventListener(uiChartViewListener listener) {
        mEventListener = listener;
    }
    static final Logger console = Logger.getLogger(uiChartView.class.getName());
    int mHilitedColumn = -1;

    public void mouseClicked(MouseEvent e) {
        Component component = e.getComponent();
        if (!component.hasFocus()) {
            component.requestFocusInWindow();
        }

        int cols = mController.getReportColumns();
        int index = cols - 1 - (e.getX() - (mCxOffset + mCxLabelOffset + mViewOffsetX)) / cxStep;
        if (index < 0) {
            return;
        }
        if (index > cols - 1) {
            return;
        }

        //console.log(Level.INFO, String.format("Column %d is hit", index));
        if (mHilitedColumn == index) {
            mHilitedColumn = -1;
        } else {
            mHilitedColumn = index;
        }

        notifyHilightChanged();
    }

    void notifyHilightChanged() {
        if (mEventListener != null) {
            mEventListener.onSelectionChanged(mHilitedColumn);
        }

        repaint();
    }

    public void mousePressed(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseReleased(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseEntered(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseExited(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    static class colorTriplet {

        int r, g, b;
    }

    /** Creates new form uiChartView */
    public uiChartView() {
        initComponents();

        addKeyListener(this);
        addMouseListener(this);
    }

    Color getColor(int index) {
        return uiColorTable.getColor(index);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setName("Form"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
    public int mCyOffset = 15;
    public int mCcCharSize = 11;
    public int mCxOffset = 10;
    public int mCxLabelOffset = 60;
    public int mHintTextSize = 15;
    protected final static int cxStep = 4;
    protected ReportViewController mController = null;

    public void setViewController(ReportViewController ctrl) {
        mController = ctrl;
    }

    public ReportViewController getViewController() {
        return mController;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        if (mController == null || mController.getSpyData() == null) {
            return;
        }

        Font oldFont, newFont;
        oldFont = g.getFont();
        newFont = new Font(oldFont.getName(), oldFont.getStyle(), mCcCharSize);
        g.setFont(newFont);

        g.setClip(0, 0, getWidth() - mCxOffset, getHeight());

        synchronized (mController.getSpyData()) {
            drawAxis(g2d);
            drawLines(g2d);
            drawHilight(g2d);
            drawHint(g2d);
        }

        g.setFont(oldFont);
    }
    int mViewOffsetX = 0;

    protected void drawLines(Graphics2D g) {
        Color oldColor = g.getColor();

        //canvas.clipRect(0, 0, getWidth() - mCxOffset, getHeight());
        int rows = mController.getReportRows();
        int cols = mController.getReportColumns();

        for (int i = 0; i < rows; i++) {
            int x0 = 0, y0 = 0;
            g.setColor(getColor(i));
            for (int j = 0; j < cols; j++) {
                int x = mCxOffset + mCxLabelOffset + (cols - j - 1) * cxStep + mViewOffsetX;
                if (x < mCxOffset + mCxLabelOffset) {
                    break;
                }
                if (x > getWidth()) {
                    continue;
                }
                int value = mController.getEntry(i, j);
                if (value == -1) {
                    continue; // the report target is either not valid or dead
                }
                int y = mCyOffset + getViewHeight() - getViewHeight() * value / 100;
                if (x0 != 0 && y0 != 0) {
                    g.drawLine(x0, y0, x, y);
                }
                x0 = x;
                y0 = y;

                if (j % 60 == 0) {
                    g.setColor(Color.BLACK);
                    g.drawString(String.format("%dmin", j / 60), x, getHeight() - 3);
                    g.setColor(getColor(i));
                }
            }
        }

        g.setColor(oldColor);
    }

    protected void drawHint(Graphics2D g) {
        Color oldColor = g.getColor();
        g.setColor(Color.BLACK);

        Font oldFont, newFont;
        oldFont = g.getFont();
        newFont = new Font(oldFont.getName(), oldFont.getStyle(), mHintTextSize);
        g.setFont(newFont);

        //getEntryName
        int cols = mController.getReportColumns();
        if (cols > 0) {
            String hint = mController.getEntryHint(cols - 1);
            if (hint != null) {
                int width = getWidth();
                int height = getHeight();
                int cx = g.getFontMetrics(g.getFont()).stringWidth(hint);
                g.drawString(hint, (width - cx) / 2, height / 2);
            }
        }

        g.setFont(oldFont);
        g.setColor(oldColor);
    }

    protected void drawHilight(Graphics2D g) {
        if (mHilitedColumn == -1) {
            return;
        }

        Color oldColor = g.getColor();

        int cols = mController.getReportColumns();
        g.setColor(Color.RED);
        int x = mCxOffset + mCxLabelOffset + (cols - mHilitedColumn - 1) * cxStep + mViewOffsetX;
        if (x < mCxOffset + mCxLabelOffset) {
            return;
        }
        if (x > (getWidth() - mCxOffset)) {
            return;
        }
        g.drawLine(x, mCyOffset, x, getHeight() - mCyOffset);

        g.setColor(oldColor);
    }

    protected int getViewWidth() {
        int nWidth = getWidth();
        return nWidth - 2 * mCxOffset - mCxLabelOffset;
    }

    protected int getViewHeight() {
        int nHeight = getHeight();
        return nHeight - 2 * mCyOffset;
    }

    protected void drawAxis(Graphics2D g) {
        int nWidth = getWidth();
        int nHeight = getHeight();

        Color oldColor = g.getColor();
      
        g.drawLine(mCxOffset + mCxLabelOffset, mCyOffset,
                mCxOffset + mCxLabelOffset, nHeight - mCyOffset);
        g.drawLine(mCxOffset + mCxLabelOffset, nHeight - mCyOffset,
                nWidth - mCxOffset, nHeight - mCyOffset);

        final float dash1[] = {5.0f};
        BasicStroke dashed = new BasicStroke(1.0f,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER,
                10.0f, dash1, 0.0f);
        Stroke oldStroke = g.getStroke();
        g.setStroke(dashed);

        int yAxisLen = nHeight - 2 * mCyOffset;
        int yStep = yAxisLen / mController.getYLabels();
        for (int i = 0; i <= mController.getYLabels(); i++) {
            g.setColor(Color.BLACK);
            String labelY = mController.stringYLabels(i);
            int nX = mCxOffset + mCxLabelOffset - g.getFontMetrics(g.getFont()).stringWidth(labelY);
            g.drawString(labelY,
                    nX, nHeight - mCyOffset - (yStep * i));
            if (i == 0) {
                continue;
            }
            g.setColor(Color.LIGHT_GRAY);
            g.drawLine(mCxOffset + mCxLabelOffset, nHeight - mCyOffset - (yStep * i),
                    nWidth - mCxOffset, nHeight - mCyOffset - (yStep * i));
        }

        g.setStroke(oldStroke);
        g.setColor(oldColor);
    }
}
